/*
 * jxUtils Project (2014)
 * 
 * by Denilson Edinaldo Pinto
 * 
 * LGPL
 * Copyright (C) 2014
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package org.jxUtils.lang;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import org.jxUtils.system.SystemProperties;

/**
 * @author Denilson Edinaldo Pinto
 * @porject jxUtils
 * @package org.jxUtils.lang
 * @date 18/01/2014 - 18:39:42
 */
public class StringAsync implements Serializable, Comparable<String>, CharSequence {
	
	private static final long serialVersionUID = -6007559046066056265L;
	
	private StringBuilder value;
	
	/**
	 * 
	 */
	public StringAsync() {
	
		value = new StringBuilder();
	}
	
	/**
	 * @param bytes
	 */
	public StringAsync(final byte bytes[]) {
	
		this(bytes, 0, bytes.length);
	}
	
	/**
	 * @param bytes
	 * @param charset
	 */
	public StringAsync(final byte bytes[], final Charset charset) {
	
		this(bytes, 0, bytes.length, charset);
	}
	
	/**
	 * @param bytes
	 * @param offset
	 * @param length
	 */
	public StringAsync(final byte bytes[], final int offset, final int length) {
	
		value = new StringBuilder(new String(bytes, offset, length));
	}
	
	/**
	 * @param bytes
	 * @param offset
	 * @param length
	 * @param charset
	 */
	public StringAsync(final byte bytes[], final int offset, final int length, final Charset charset) {
	
		value = new StringBuilder(new String(bytes, offset, length, charset));
	}
	
	/**
	 * @param bytes
	 * @param offset
	 * @param length
	 * @param charsetName
	 * @throws UnsupportedEncodingException
	 */
	public StringAsync(final byte bytes[], final int offset, final int length, final String charsetName) throws UnsupportedEncodingException {
	
		value = new StringBuilder(new String(bytes, offset, length, charsetName));
	}
	
	/**
	 * @param bytes
	 * @param charsetName
	 * @throws UnsupportedEncodingException
	 */
	public StringAsync(final byte bytes[], final String charsetName) throws UnsupportedEncodingException {
	
		this(bytes, 0, bytes.length, charsetName);
	}
	
	/**
	 * @param value
	 */
	public StringAsync(final char value[]) {
	
		this.value = new StringBuilder(new String(value));
	}
	
	/**
	 * @param value
	 * @param offset
	 * @param count
	 */
	public StringAsync(final char value[], final int offset, final int count) {
	
		this.value = new StringBuilder(new String(value, offset, count));
	}
	
	/**
	 * @param codePoints
	 * @param offset
	 * @param count
	 */
	public StringAsync(final int[] codePoints, final int offset, final int count) {
	
		value = new StringBuilder(new String(codePoints, offset, count));
	}
	
	/**
	 * @param original
	 */
	public StringAsync(final String original) {
	
		value = new StringBuilder(original);
	}
	
	/**
	 * @param builder
	 */
	public StringAsync(final StringBuilder builder) {
	
		value = builder;
	}
	
	/**
	 * @param str
	 * @param value
	 * @param repeat
	 * @param before
	 * @return Returns the value <b>"value"</b> concatenated <b>"repeat"</b> times at the beginning or end of <b>"str"</b> in
	 *         accordance with the <b>"before"</b> parameter
	 */
	public static String concat(final String str, final String value, final int repeat, final boolean before) {
	
		return StringUtil.concat(str, value, repeat, before).toString();
	}
	
	/**
	 * @param b
	 */
	public final StringBuilder append(final boolean b) {
	
		return value.append(b);
	}
	
	/**
	 * @param c
	 */
	public final StringBuilder append(final char c) {
	
		return value.append(c);
	}
	
	/**
	 * @param str
	 */
	public final StringBuilder append(final char[] str) {
	
		return value.append(str);
	}
	
	/**
	 * @param str
	 * @param offset
	 * @param len
	 */
	public final StringBuilder append(final char[] str, final int offset, final int len) {
	
		return value.append(str, offset, len);
	}
	
	/**
     */
	public final StringBuilder append(final CharSequence s) {
	
		return value.append(s);
	}
	
	/**
	 * @param s
	 * @param start
	 * @param end
	 */
	public final StringBuilder append(final CharSequence s, final int start, final int end) {
	
		return value.append(s, start, end);
	}
	
	/**
	 * @param d
	 */
	public final StringBuilder append(final double d) {
	
		return value.append(d);
	}
	
	/**
	 * @param f
	 */
	public final StringBuilder append(final float f) {
	
		return value.append(f);
	}
	
	/**
	 * @param i
	 */
	public final StringBuilder append(final int i) {
	
		return value.append(i);
	}
	
	/**
	 * @param lng
	 */
	public final StringBuilder append(final long lng) {
	
		return value.append(lng);
	}
	
	/**
	 * @param obj
	 */
	public final StringBuilder append(final Object obj) {
	
		return value.append(obj);
	}
	
	/**
	 * @param str
	 */
	public final StringBuilder append(final String str) {
	
		return value.append(str);
	}
	
	/**
	 * @param sb
	 */
	public final StringBuilder append(final StringBuffer sb) {
	
		return value.append(sb);
	}
	
	/**
	 * @param codePoint
	 */
	public final StringBuilder appendCodePoint(final int codePoint) {
	
		return value.appendCodePoint(codePoint);
	}
	
	/**
	 * @param codePoint
	 */
	public final StringBuilder appendCodePointNewLine(final int codePoint) {
	
		appendLine();
		
		return appendCodePoint(codePoint);
	}
	
	/**
	 * 
	 */
	public final void appendLine() {
	
		value.append(SystemProperties.getLineSeparator());
	}
	
	/**
	 * @param b
	 */
	public final StringBuilder appendLine(final boolean b) {
	
		appendLine();
		
		return append(b);
	}
	
	/**
	 * @param c
	 */
	public final StringBuilder appendLine(final char c) {
	
		appendLine();
		
		return append(c);
	}
	
	/**
	 * @param str
	 */
	public final StringBuilder appendLine(final char[] str) {
	
		appendLine();
		
		return append(str);
	}
	
	/**
	 * @param str
	 * @param offset
	 * @param len
	 */
	public final StringBuilder appendLine(final char[] str, final int offset, final int len) {
	
		appendLine();
		
		return append(str, offset, len);
	}
	
	/**
     */
	public final StringBuilder appendLine(final CharSequence s) {
	
		appendLine();
		
		return append(s);
	}
	
	/**
	 * @param s
	 * @param start
	 * @param end
	 */
	public final StringBuilder appendLine(final CharSequence s, final int start, final int end) {
	
		appendLine();
		
		return append(s, start, end);
	}
	
	/**
	 * @param d
	 */
	public final StringBuilder appendLine(final double d) {
	
		appendLine();
		
		return append(d);
	}
	
	/**
	 * @param f
	 */
	public final StringBuilder appendLine(final float f) {
	
		appendLine();
		
		return append(f);
	}
	
	/**
	 * @param i
	 */
	public final StringBuilder appendLine(final int i) {
	
		appendLine();
		
		return append(i);
	}
	
	/**
	 * @param lng
	 */
	public final StringBuilder appendLine(final long lng) {
	
		appendLine();
		
		return append(lng);
	}
	
	/**
	 * @param obj
	 */
	public final StringBuilder appendLine(final Object obj) {
	
		appendLine();
		
		return append(obj);
	}
	
	/**
	 * @param str
	 */
	public final StringBuilder appendLine(final String str) {
	
		appendLine();
		
		return append(str);
	}
	
	/**
	 * @param sb
	 */
	public final StringBuilder appendLine(final StringBuffer sb) {
	
		appendLine();
		
		return append(sb);
	}
	
	/**
	 * 
	 */
	@Override
	public final char charAt(final int index) {
	
		return value.charAt(index);
	}
	
	/**
	 * 
	 */
	@Override
	public final int compareTo(final String anotherString) {
	
		return value.toString().compareTo(anotherString);
	}
	
	/**
	 * @param value
	 * @param repeat
	 * @param before
	 * @return Returns the value <b>"value"</b> concatenated <b>"repeat"</b> times at the beginning or end of <b>"this"</b> in
	 *         accordance with the <b>"before"</b> parameter
	 */
	public void concat(final String value, final int repeat, final boolean before) {
	
		this.value = StringUtil.concat(this, value, repeat, before);
	}
	
	/**
	 * @return value
	 */
	public final StringBuilder getValue() {
	
		return value;
	}
	
	/**
	 * Returns <tt>true</tt> if, and only if, {@link #trim()} . {@link #length()} is <tt>0</tt>.
	 * 
	 * @return <tt>true</tt> if {@link #trim()} . {@link #length()} is <tt>0</tt>, otherwise <tt>false</tt>
	 */
	public boolean isAbsoluteEmpty() {
	
		return trim().isEmpty();
	}
	
	/**
	 * Returns <tt>true</tt> if, and only if, {@link #length()} is <tt>0</tt>.
	 * 
	 * @return <tt>true</tt> if {@link #length()} is <tt>0</tt>, otherwise <tt>false</tt>
	 */
	public boolean isEmpty() {
	
		return length() == 0;
	}
	
	/**
	 * 
	 */
	@Override
	public final int length() {
	
		return value.length();
	}
	
	/**
	 * @return reverse StringBuilder
	 */
	public StringBuilder reverse() {
	
		return value.reverse();
	}
	
	/**
	 * 
	 */
	@Override
	public final CharSequence subSequence(final int start, final int end) {
	
		return value.subSequence(start, end);
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
	
		return getValue().toString();
	}
	
	/**
	 * Returns a copy of the string, with leading and trailing whitespace
	 * omitted.
	 * <p>
	 * If this <code>String</code> object represents an empty character sequence, or the first and last characters of character sequence represented by this <code>String</code> object both have codes greater than <code>'&#92;u0020'</code> (the space character), then a reference to this <code>String</code> object is returned.
	 * <p>
	 * Otherwise, if there is no character with a code greater than <code>'&#92;u0020'</code> in the string, then a new <code>String</code> object representing an empty string is created and returned.
	 * <p>
	 * Otherwise, let <i>k</i> be the index of the first character in the string whose code is greater than <code>'&#92;u0020'</code>, and let <i>m</i> be the index of the last character in the string whose code is greater than <code>'&#92;u0020'</code>. A new <code>String</code> object is created, representing the substring of this string that begins with the character at index <i>k</i> and ends with the character at index <i>m</i>-that is, the result of <code>substring(<i>k</i>,&nbsp;<i>m</i>+1)</code>.
	 * <p>
	 * This method may be used to trim whitespace (as defined above) from the beginning and end of a string.
	 * 
	 * @return A copy of this {@link StringAsync} with leading and trailing white
	 *         space removed, or this string if it has no leading or
	 *         trailing white space.
	 */
	public StringAsync trim() {
	
		return new StringAsync(getValue().toString().trim());
	}
}
